package data_search

import (
	"GraduationProject/public/db"
	"GraduationProject/public/models"
	"GraduationProject/webserver/controllers/util"
	"archive/zip"
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"strconv"
	"time"
)

func OutPut(c *gin.Context) {
	_, err := util.AdminFilter(c)
	if err != nil {
		return
	}

	//seedID, err := util.PostFormInt(c, "seed_id")
	seedID, err := strconv.Atoi(c.Query("seed_id"))
	if err != nil {
		util.FailedResponse(c, 10001, "seed_id: 输入参数类型错误")
		return
	}

	zipBuffer := bytes.NewBuffer(nil)
	zipWriter := zip.NewWriter(zipBuffer)
	limit := 30000
	var total int
	db.DB.Model(&models.Record{}).Where("seed_id = ?", seedID).Count(&total)
	for offset := 0; offset < limit; offset += limit {
		var records []models.Record
		db.DB.Where("seed_id = ?", seedID).
			Limit(limit).Offset(offset).Find(&records)

		csvBuffer := createCsv(&records)
		csvFile, err := zipWriter.Create(strconv.Itoa(offset) + "-" + strconv.Itoa(offset+limit) + ".csv")
		if err != nil {
			log.Printf("OutPut zipWriter.Create error: %s\n", err.Error())
			continue
		}
		_, err = csvFile.Write(csvBuffer.Bytes())
		if err != nil {
			log.Printf("OutPut csvFile.Write error: %s\n", err.Error())
			continue
		}
	}
	if err := zipWriter.Close(); err != nil {
		log.Printf("OutPut zipWriter.Close error: %s\n", err.Error())
		util.FailedResponse(c, 10001, "导出失败")
		return
	}

	c.Writer.Header().Add("Content-Type", "application/form-data")
	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%v.zip"`, time.Now().Unix()))
	_, err = zipBuffer.WriteTo(c.Writer)
	if err != nil {
		log.Printf("OutPut zipBuffer.WriteTo error: %s\n", err.Error())
		util.FailedResponse(c, 10001, "传输失败")
		return
	}
}

func createCsv(records *[]models.Record) *bytes.Buffer {
	csvBuffer := bytes.NewBuffer(nil)
	csvWriter := csv.NewWriter(csvBuffer)
	if err := csvWriter.WriteAll(getData(records)); err != nil {
		panic(err)
	}

	return csvBuffer
}

func getData(records *[]models.Record) [][]string {
	rLen := len(*records)
	data := make([][]string, rLen+1)
	data[0] = []string{
		"ID", "CreatedAt", "UpdatedAt", "NotElastic", "SeedID",
		"Url", "Params", "FunctionName", "Error", "Result", "Remarks",
	}

	for i, v := range *records {
		notElastic := "false"
		if v.NotElastic {
			notElastic = "true"
		}
		data[i+1] = []string{
			strconv.Itoa(int(v.ID)), v.CreatedAt.String(),
			v.UpdatedAt.String(), notElastic, strconv.Itoa(int(v.SeedID)),
			v.Url, v.Params, v.FunctionName, v.Error,
			v.Result, v.Remarks,
		}
	}

	return data
}
